<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<script>
let plugin = (function() {
  let plugin = document.createElement('embed');
  plugin.style.display = 'none';

  plugin.type = 'application/txftn-webkit';
  plugin.sign = function() {
    console.log('开始文件扫描');
  }
  plugin.pause = function() {
    console.log('暂停文件上传');
  }
  plugin.uploading = function() {
    console.log('开始文件上传');
  }
  plugin.del = function() {
    console.log('删除文件上传');
  }
  plugin.done = function() {
    console.log('文件上传完成');
  }
  document.body.appendChild(plugin);
  return plugin;
})()
class Upload {
  constructor(fileName) {
    this.plugin = plugin;
    this.fileName = fileName;
    this.button1 = null;
    this.button2 = null;
    this.signState = new SignState(this);
    this.uploadingState = new UploadingState(this);
    this.pauseState = new PauseState(this);
    this.doneState = new DoneState(this);
    this.errorState = new ErrorState(this);
    this.currState = this.signState;
  }
  init() {
    // 创建节点：用于控制上传流程的按钮
    this.dom = document.createElement('div');
    this.dom.innerHTML = `
      <span>文件名称：${this.fileName}</span>
      <button data-action="button1">扫描中</button>
      <button data-action="button2">删除</button>
    `
    document.body.appendChild(this.dom)
    this.button1 = this.dom.querySelector('[data-action="button1"]')
    this.button2 = this.dom.querySelector('[data-action="button2"]')
    // 绑定点击事件
    this.bindEvent()
  }
  bindEvent() {
    this.button1.onclick = () => {
      this.currState.clickHandle1();
    }
    this.button2.onclick = () => {
      this.currState.clickHandle2();
    }
  }
  sign() {
    this.plugin.sign();
    this.button1.innerHTML = '扫描中，任何操作无效';
    this.currState = this.signState;
  }
  uploading() {
    this.plugin.uploading();
    this.button1.innerHTML = '正在上传，点击暂停';
    this.currState = this.uploadingState;
  }
  pause() {
    this.plugin.pause();
    this.button1.innerHTML = '已暂停，点击继续上传';
    this.currState = this.pauseState;
  }
  done() {
    this.plugin.done();
    this.button1.innerHTML = '上传完成';
    this.currState = this.uploadingState;
  }
  error() {
    this.button1.innerHTML = '上传失败';
    this.currState = this.errorState;
  }
  del() {
    this.plugin.del();
    this.dom.parentNode.removeChild(this.dom);
  }
}
class State {
  constructor(uploadObj) {
    this.uploadObj = uploadObj;
  }
  clickHandle1() {
    throw new Error('父类的clickHandle1方法必须被重写')
  }
  clickHandle2() {
    throw new Error('父类的clickHandle2方法必须被重写')
  }
}
class SignState extends State {
  constructor(uploadObj) {
    super(uploadObj)
  }
  clickHandle1() {
    console.log('扫描中，点击无效...');
  }
  clickHandle2() {
    console.log('文件正在扫描中，不能删除'); 
  }
}
class UploadingState extends State {
  constructor(uploadObj) {
    super(uploadObj)
  }
  clickHandle1() {
    this.uploadObj.pause();
  }
  clickHandle2() {
    this.uploadObj.del();
  }
}
class PauseState extends State {
  constructor(uploadObj) {
    super(uploadObj)
  }
  clickHandle1() {
    this.uploadObj.uploading();
  }
  clickHandle2() {
    this.uploadObj.del();
  }
}
class DoneState extends State {
  constructor(uploadObj) {
    super(uploadObj)
  }
  clickHandle1() {
    console.log('文件已完成上传, 点击无效'); 
  }
  clickHandle2() {
    this.uploadObj.del();
  }
}
class ErrorState extends State {
  constructor(uploadObj) {
    super(uploadObj)
  }
  clickHandle1() {
    console.log('文件上传失败, 点击无效');
  }
  clickHandle2() {
    this.uploadObj.del();
  }
}

let uploadObj = new Upload('js设计模式与开发实践')
uploadObj.init()

window.external.upload = function(state) {
  uploadObj[state]()
}
window.external.upload('sign') // 文件开始扫描
setTimeout(() => {
  window.external.upload('uploading'); // 1 秒后开始上传
}, 1000);
setTimeout(() => {
  window.external.upload('done'); // 5 秒后上传完成
}, 5000);
</script>
</body>
</html>